<?php

class WarehouseService extends AbstractService
{
    /**
     * @var WarehouseService
     */
    private static $instance;

    /**
     * Get instance of WarehouseService.
     *
     * @return WarehouseService
     */
    public static function get()
    {
        if (!self::$instance) {
            self::$instance = new WarehouseService();
        }
        return self::$instance;
    }

    /**
     * Construction.
     */
    protected function __construct()
    {
        parent::__construct();
    }

    /**
     * 处理用户创建时的逻辑
     *
     * @param int $shardId
     * @return void
     */
    public function handleCreate($shardId)
    {
        // do nothing
    }

    /**
     * 处理用户登录时的逻辑
     *
     * @param int $userId
     * @return void
     */
    public function handleLogin($userId)
    {
        $this->checkWarehouseStockByFirstLogin($userId);
    }

    /**
     * 提供当前 service 数据
     *
     * @param int $userId
     * @param boolean $visitMode default false
     * @return array(WarehouseVoList)
     */
    public function info($userId, $visitMode = false)
    {
        $warehouseList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_WAREHOUSE);
        return array(
            $warehouseList
        );
    }

    /**
     * 处理仓库数量增减逻辑，需要验证仓库上限
     *
     * @see GameService::handleEntity
     * @param int $userId
     * @param int $buildingDefId
     * @param int $decorId
     * @throws SzException 20101
     * @return WarehouseVoList
     */
    public function init($userId, $buildingDefId, $decorId)
    {
        $warehouseSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_BUILDING_WAREHOUSE, $buildingDefId, true);
        $warehouseId = $warehouseSetting['warehouseId'];

        /**
         * @var WarehouseVoList $warehouseList
         * @var WarehouseVo $warehouse
         */
        $warehouseList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_WAREHOUSE);
        $warehouse = $warehouseList->getElement($warehouseId, false);

        if ($warehouse != null) {
            return $warehouseList;
        }

        $warehouse = new WarehouseVo($userId, $warehouseId, $decorId, 0, true);
        $warehouseList->addElement($warehouse);
        $warehouseList->setElement($warehouseId, $warehouse);

        SzPersister::get()->setVoList($warehouseList);

        return $warehouseList;
    }


    /**
     * 处理仓库数量增减逻辑，需要验证仓库上限
     *
     * @see GameService::handleEntity
     * @param int $userId
     * @param int $itemDefId
     * @param int $count
     * @param boolean $allowExceedLimit default false
     * @throws SzException 20042
     * @return int $count
     */
    public function processWarehouse($userId, $itemDefId, $count, $allowExceedLimit = false)
    {
        return $count;
        $itemSetting = SzConfig::get()->loadAppConfig(ModuleItemConst::CONFIG_ITEM_DEFS, $itemDefId, true);
        $warehouseId = $itemSetting['warehouseId'];

        if ($warehouseId < 0) {
            return $count;
        }

        /**
         * @var WarehouseVoList $warehouseList
         * @var WarehouseVo $warehouse
         */
        $warehouseList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_WAREHOUSE);
        $warehouse = $warehouseList->getElement($warehouseId);

        if ($count <= 0) {
            if ($warehouse->getStock() < abs($count)) {
                $count = -$warehouse->getStock();
            }
        } else {
            if (!$allowExceedLimit) {
                /**
                 * @var BuildingVoList $buildingList
                 * @var BuildingVo $building
                 */
                $buildingList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_BUILDING);
                $building = $buildingList->getElement($warehouse->getDecorId());
                $buildingDefId = $building->getBuildingDefId();
                $warehouseSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_BUILDING_WAREHOUSE, $buildingDefId, true);

                if ($warehouse->getStock() >= $warehouseSetting['itemLimit']) {
                    throw new SzException(20042, array($buildingDefId, $warehouse->getStock(), $warehouseSetting['itemLimit']));
                }
            }
        }

        if ($count != 0) {
            $warehouse->updateStock($count);
            $warehouse->persist();
            $warehouseList->updateElement($warehouseId, $warehouse);

            SzPersister::get()->setVoList($warehouseList);
        }

        return $count;
    }

    /**
     * 每日首次登录检查仓库数据
     * @param int $userId
     * @return void
     * @throws SzException
     */
    public function checkWarehouseStockByFirstLogin($userId)
    {
        if (GameService::get()->isDailyFirstLogin($userId) == false) {
            return;
        }

        $itemList = SzPersister::get()->getVoList($userId, ModuleItemConst::ORM_NAME_ITEM);

        /**
         * @var ModuleItemVo $itemVo
         */

        $itemSettings = SzConfig::get()->loadAppConfig(ModuleItemConst::CONFIG_ITEM_DEFS, null, true);

        $stocks = [];
        foreach ($itemList->getList() as $itemDefId => $items) {
            if (!isset($itemSettings[$itemDefId]) || $itemSettings[$itemDefId]['warehouseId'] < 0) {
                continue;
            }
            $itemCount = 0;
            foreach ($items as $itemVo) {
                $itemCount += $itemVo->getCount();
            }
            if (isset($stocks[$itemSettings[$itemDefId]['warehouseId']])) {
                $stocks[$itemSettings[$itemDefId]['warehouseId']] += $itemCount;
            } else {
                $stocks[$itemSettings[$itemDefId]['warehouseId']] = $itemCount;
            }
        }

        /**
         * @var WarehouseVoList $warehouseList
         * @var WarehouseVo $warehouse
         */
        $warehouseList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_WAREHOUSE);
        foreach ($stocks as $warehouseId => $count) {
            $warehouse = $warehouseList->getElement($warehouseId, false);
            if (!$warehouse) {
                continue;
            }
            if ($warehouse->getStock() != $count) {
                $warehouse->setStock($count);
                $warehouseList->updateElement($warehouseId, $warehouse);
            }
        }
        SzPersister::get()->setVoList($warehouseList);
    }

    /**
     * 获取仓库等级
     * @param $userId
     * @return array($warehouseId => $level)
     */
    public function getWarehouseLevel($userId)
    {
        $levels = [];
        /**
         * @var WarehouseVoList $warehouseList
         * @var WarehouseVo $warehouse
         * @var BuildingVoList $buildingList
         * @var BuildingVo $building
         */
        $warehouseList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_WAREHOUSE);

        $buildingList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_BUILDING);
        foreach ($warehouseList->getList() as $warehouseId => $warehouse) {
            $decorId = $warehouse->getDecorId();
            $building = $buildingList->getElement($decorId, false);
            if ($building) {
                $buildingDefId = $building->getBuildingDefId();
                $levels[$warehouseId] = $this->getLevelByBuildingDefId($buildingDefId);
            }
        }
        SzPersister::get()->setVoList($warehouseList);
        return $levels;
    }

    /**
     * 解锁建筑id获得仓库等级
     * @param $buildingDefId
     * @return int
     */
    public function getLevelByBuildingDefId($buildingDefId)
    {
        return $buildingDefId % 100;
    }
}
